/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package compilador.analisadorSintatico.classe;

import compilador.analisadorLexico.PalavraReservada;
import compilador.analisadorSintatico.Producao;
import compilador.analisadorLexico.Token;
import compilador.analisadorLexico.TokenClass;
import compilador.analisadorSintatico.simboloGramatical.SimboloGramatical;
import compilador.analisadorSintatico.TokenReader;
import compilador.analisadorSintatico.simboloGramatical.NaoTerminal;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;

/**
 *
 * 
 * @author Matheus Cardoso
 */
public class EXP_CLASSE extends Producao{
    
    Token token = null;
    Token next = null;
    
    @Override
    public SimboloGramatical derivar() throws Exception {
        TokenReader tokenReader = TokenReader.getInstance();
        
        atualizarTokens(tokenReader); //atualiza token e next
        
        while(tokenReader.hasToken()){
            if(token.getTokenClass().equals(TokenClass.DELIMITADOR) && token.getAtributo().equals("}"))
                return simbolo;
            
            if(token.getAtributo().equals(PalavraReservada.CHAR)
                    || token.getAtributo().equals(PalavraReservada.INT)
                    || token.getTokenClass().equals(TokenClass.IDENTIFICADOR)) {
                
                next = tokenReader.seeNext();
                if(next.getTokenClass().equals(TokenClass.OPERADOR) && next.getAtributo().equals("[")){
                    ((NaoTerminal) simbolo).add(new DEC_VARIAVEL().derivar());
                    atualizarTokens(tokenReader); //atualiza token e next
                }
                else if(next.getTokenClass().equals(TokenClass.IDENTIFICADOR)){
                        next = tokenReader.seeNext(2);
                        if(next.getTokenClass().equals(TokenClass.DELIMITADOR) && next.getAtributo().equals("(")){
                            ((NaoTerminal) simbolo).add(new DEC_METODO().derivar());
                            atualizarTokens(tokenReader); //atualiza token e next
                        }
                        else {
                            ((NaoTerminal) simbolo).add(new DEC_VARIAVEL().derivar());
                            atualizarTokens(tokenReader); //atualiza token e next
                        }
                }
                else
                    erro("'" +token.getAtributo() + "' Declaração de método ou variável não reconhecida.");
            }
            /*else if(token.getAtributo().equals(PalavraReservada.INT)){
                next = tokenReader.seeNext();
                if(next.getTokenClass().equals(TokenClass.OPERADOR) && next.getAtributo().equals("[")){
                    ((NaoTerminal) simbolo).add(new DEC_VARIAVEL().derivar());
                    atualizarTokens(tokenReader); //atualiza token e next
                }
                else if(next.getTokenClass().equals(TokenClass.IDENTIFICADOR)){
                        next = tokenReader.seeNext(2);
                        if(next.getTokenClass().equals(TokenClass.DELIMITADOR) && next.getAtributo().equals("(")){
                            ((NaoTerminal) simbolo).add(new DEC_METODO().derivar());
                            atualizarTokens(tokenReader); //atualiza token e next
                        }
                        else {
                            ((NaoTerminal) simbolo).add(new DEC_VARIAVEL().derivar());
                            atualizarTokens(tokenReader); //atualiza token e next
                        }
                }
            }*/
            else if(token.getAtributo().equals(PalavraReservada.VOID))
                ((NaoTerminal) simbolo).add(new DEC_METODO().derivar());
                
            else if(token.getAtributo().equals(PalavraReservada.CLASS))
                ((NaoTerminal) simbolo).add(new DEC_CLASSE_INTERNA().derivar());
            
            else if(token.getAtributo().equals(PalavraReservada.CONST)){
                next = tokenReader.seeNext();
                ((NaoTerminal) simbolo).add(new DEC_CONSTANTE().derivar());
                
            }
            else
            {
                tokenReader.consome(); // o método do erro considera que o token atual (e não o próximo) é o primeiro errado
                erro("'" +token.getAtributo() + "' Declaração de método ou variável não reconhecida.");
            }
            
            atualizarTokens(tokenReader); //atualiza token e next
        }
        
        return simbolo;
    }

    private void atualizarTokens(TokenReader tokenReader) {

        token = tokenReader.seeCurrent();
        next = tokenReader.seeNext();
    }

    @Override
    public void setSimbolo() {
        simbolo = new NaoTerminal(this.getClass().getSimpleName());
    }

}
